﻿using System;
using System.Collections.Generic;
using System.Reflection;
using Service.Infrastructure.Result;
using SystmicFunction.IRMHelper;

namespace Service.Infrastructure
{
    /// <summary>
    ///     工作流处理
    /// </summary>
    internal class WorkProcess
    {
        /// <summary>
        ///     异常处理字典
        /// </summary>
        public static readonly Dictionary<String, Object> ExceptionDict = new Dictionary<string, Object>
        {
            {"System.InvalidOperationException",ResultType.TargetIsNotFound}
        };

        public TokenData TokenData;

        private readonly ServiceResult _result;

        public WorkProcess(BaseService thisService, ServiceResult result)
        {
            TokenData = new TokenData(thisService, this);
            _result = result;
        }

        public delegate ServiceResult DoWorkFunc(params Object[] inParams);

        /// <summary>
        ///  流程执行
        /// </summary>
        /// <param name="excuteParams">执行内容：类名-方法名</param>
        /// <param name="finallyResultType">最终返回状态码</param>
        /// <param name="type">要转换对象的类名</param>
        /// <param name="turnParam">要转换的属性名对应关系：Key 属性名 Value 类名-属性名</param>
        /// <returns>返回Service处理结果</returns>
        public ServiceResult DoProcess(Dictionary<String, Object[]> excuteParams, ResultType finallyResultType, Type type, Dictionary<String, String> turnParam)
        {

            //TODO:字典是否有序
            foreach (var excuteParam in excuteParams)
            {
                var classNameMethodName = excuteParam.Key.Split('-');
                try
                {
                    TokenData.Data = DoWork(Type.GetType(classNameMethodName[0]), classNameMethodName[1], excuteParam.Value);
                }
                catch (Exception e)
                //没有元素满足 predicate 中的条件。- 或 -多个元素满足 predicate 中的条件。- 或 -源序列为空
                {
                    _result.SetCode(ExceptionHandle.CheckException(e, ExceptionDict)); 
                    return _result;
                }

            }

            _result.SetCode(finallyResultType);
            _result.SetData(TokenData.Data);
            return _result;
        }

        /// <summary>
        ///  将逻辑对象转化为业务对象
        /// </summary>
        /// <param name="opData">传入数据</param>
        /// <param name="resultType">返回的对象类型</param>
        /// <param name="dict">Key:返回对象的属性名 value:返回对象对应的属性名</param>
        /// <returns>转化完成的对象</returns>
        public Object ChangeObject(Object opData, Type resultType, Dictionary<string, string> dict)
        {
            Type opType = opData.GetType();

            //判断是集合或对象
            if (opType == Type.GetType("System.Collections.Generic.IList`1"))
            {
                IList<Object> resultlist = new List<object>();

                resultlist.Add(new object());
                object genericList = CreateGeneric(typeof(List<>), resultType);
                return resultlist;
            }
            else
            {
                return NewResultObj(opType, opData, resultType, dict);
            }

        }

        public static object CreateGeneric(Type generic, Type innerType, params object[] args)
        {
            Type specificType = generic.MakeGenericType(new System.Type[] { innerType });
            return Activator.CreateInstance(specificType, args);
        }
       

        /// <summary>
        ///     根据Op返回对象
        /// </summary>
        /// <param name="opType"></param>
        /// <param name="opData"></param>
        /// <param name="resultType"></param>
        /// <param name="dict"></param>
        /// <returns></returns>
        public Object NewResultObj(Type opType, Object opData, Type resultType, Dictionary<String, String> dict)
        {
            Object resultObj = Activator.CreateInstance(resultType);
            foreach (var model in dict)
            {
                var opPropertyValue = opType.GetProperty(model.Value.Split('-')[1]).GetValue(opData, null);
                resultType.GetProperty(model.Key).SetValue(resultObj, opPropertyValue, null);
            }
            return resultObj;
        }

        /// <summary>
        ///     执行
        /// </summary>
        /// <param name="type">执行类名</param>
        /// <param name="methodName">方法名</param>
        /// <param name="inParams">执行参数</param>
        /// <returns>处理返回数据：Void无返回值</returns>
        public Object DoWork(Type type, String methodName, params Object[] inParams)
        {
            return DoWork(type, methodName, null, inParams);
        }

        /// <summary>
        ///     执行
        /// </summary>
        /// <param name="type">执行类名</param>
        /// <param name="methodName">方法名</param>
        /// <param name="tokenData">上下文交替数据</param>
        /// <param name="inParams">执行参数</param>
        /// <returns>处理返回数据：Void无返回值</returns>
        public Object DoWork(Type type, String methodName, TokenData tokenData, params Object[] inParams)
        {
            Object opObject = Activator.CreateInstance(type);

            if (tokenData.Data != null)
            {
                //工作流数据赋值
                type.GetProperty("ProcessData").SetValue(opObject, tokenData.Data, null);
            }

            System.Reflection.MethodInfo method = type.GetMethod(methodName);

            return method.Invoke(opObject, inParams);
        }



    }

    internal class TokenData
    {
        public Object Data;
        private Int32 _serviceToken;
        private Int32 _processToken;

        public TokenData(BaseService thisService, WorkProcess thisProcess)
        {
            _serviceToken = thisService.GetHashCode();
            _processToken = thisProcess.GetHashCode();
        }
    }

}
